package com.shuyixiao;

/**
 * @author 舒一笑
 * @version 1.0.0
 * @ClassName GitLabDetailedStatsThreadPool.java
 * @Description 线程池优化版
 * @createTime 2023年10月08日 16:01:00
 */

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class GitLabDetailedStatsThreadPool {

    /**
     * 项目ID
     */
    static String projectID = "129";

    /**
     * 分支名称
     */
    static String refName = "release";

    /**
     * GitLab Token
     */
    static String privateToken = "glpat-UHm-qN7qpBexdAu1MkXU";

    static DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;

    /**
     * 开始时间
     */
    static String since = "2023-01-01T00:00:00Z";

    /**
     * 结束时间，这里使用当前时间
     */
    static String until = LocalDateTime.now().format(formatter);

    static int pageNumber = 1;

    /**
     * 最大值为 10000
     */
    static int commitsPerPage = 10000;

    public static void main(String[] args) throws IOException {
        LocalDateTime startTime = LocalDateTime.now();
        // 无时间限制
        CloseableHttpClient httpClientTotal = HttpClients.createDefault();
        HttpGet requestTotal = new HttpGet("http://gitlab.hzzcdz.com/api/v4/projects/" + projectID + "/repository/commits?ref_name="+refName+"&page=" + pageNumber + "&per_page=" + commitsPerPage);
        requestTotal.addHeader("PRIVATE-TOKEN", privateToken);
        HttpResponse responseTotal = httpClientTotal.execute(requestTotal);
        String responseStringTotal = EntityUtils.toString(responseTotal.getEntity(), "UTF-8");
        JSONArray commitsArrayTotal = new JSONArray(responseStringTotal);
        // 存在时间限制
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet request = new HttpGet("http://gitlab.hzzcdz.com/api/v4/projects/" + projectID + "/repository/commits?ref_name=" + refName + "&since=" + since + "&until=" + until + "&page=" + pageNumber + "&per_page=" + commitsPerPage);
        request.addHeader("PRIVATE-TOKEN", privateToken);
        HttpResponse response = httpClient.execute(request);
        String responseString = EntityUtils.toString(response.getEntity(), "UTF-8");
        JSONArray commitsArray = new JSONArray(responseString);
        // 获取项目成员
        List<Object> list = commitsArray.toList();
        List<Map<String, Object>> commitList = list.stream()
                .map(obj -> (Map<String, Object>) obj)
                .collect(Collectors.toList());
        // 转为List,取出每个commit的author_name
        List<String> members = commitList.stream()
                .map(commit -> (String) commit.get("author_name"))
                .distinct() // 去重
                .collect(Collectors.toList());
        // 获取成员的代码提交次数
        Map<String, Integer> authorCommitCounts = new HashMap<>();
        for (int i = 0; i < list.size(); i++) {
            Object authorName = commitList.get(i).get("author_name");
            authorCommitCounts.put((String) authorName, authorCommitCounts.getOrDefault(authorName, 0) + 1);
        }
        // 打印每个人的提交次数
        authorCommitCounts.forEach((author, count) -> System.out.println(author + "的总共提交次数: " + count));
        System.out.println("--------------------------------");

        //创建一个固定大小的线程池，大小根据实际情况调整
        int corePoolSize = 5;
        int maximumPoolSize = 10;
        long keepAliveTime = 60L;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();

        ExecutorService executorService = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue
        );

        for (String userName : members) {

            int[] totalStats = getStatsForUserTotal(executorService, userName, commitsArrayTotal);
            System.out.println(userName + "总的代码新增行数: " + totalStats[0]);
            System.out.println(userName + "总的代码删除行数: " + totalStats[1]);
            System.out.println(userName + "总的贡献代码总行数: " + (totalStats[0] - totalStats[1]));

            int[] quarterStats = getStatsForUser(executorService, userName, commitsArray, since, until);
            System.out.println(userName + "该季度的代码新增行数: " + quarterStats[0]);
            System.out.println(userName + "该季度的代码删除行数: " + quarterStats[1]);
            System.out.println(userName + "该季度的贡献代码总行数: " + (quarterStats[0] - quarterStats[1]));
        }

        executorService.shutdown();
        LocalDateTime endTime = LocalDateTime.now();
        Duration duration = Duration.between(startTime, endTime);
        long diff = duration.getSeconds(); // Get difference in seconds
        System.out.println("时间花费了: " + diff + " seconds");
    }

    private static int[] getStatsForUserTotal(ExecutorService executorService, String userName, JSONArray commitsArray) {
        int totalAdditions = 0;
        int totalDeletions = 0;
        // 存储任务返回结果的列表
        List<Future<int[]>> futures = new ArrayList<>();
        for (int i = 0; i < commitsArray.length(); i++) {
            JSONObject commit = commitsArray.getJSONObject(i);
            // 提交任务到线程池
            Future<int[]> future = executorService.submit(() -> {
                if (since != null && until != null) {
                    String commitDate = commit.getString("created_at");
                    if (commitDate.compareTo(since) < 0 || commitDate.compareTo(until) > 0) {
                        return new int[]{0, 0};
                    }
                }
                if (!commit.getString("author_name").equals(userName)) {
                    return new int[]{0, 0};
                }
                String commitSha = commit.getString("id");
                HttpGet diffRequest = new HttpGet("http://gitlab.hzzcdz.com/api/v4/projects/" + projectID + "/repository/commits/" + commitSha + "/diff");
                diffRequest.addHeader("PRIVATE-TOKEN", privateToken);
                CloseableHttpClient client = HttpClients.createDefault();
                CloseableHttpResponse diffResponse = client.execute(diffRequest);
                if (diffResponse.getStatusLine().getStatusCode() != 200) {
                    System.out.println("Failed to get diff: " + diffResponse.getStatusLine().getReasonPhrase());
                    diffResponse.close();
                    return new int[]{0, 0};
                }
                String diffResponseBody = EntityUtils.toString(diffResponse.getEntity());
                diffResponse.close();
                JSONArray diffs = new JSONArray(diffResponseBody);
                int[] counts = new int[2];
                for (int j = 0; j < diffs.length(); j++) {
                    JSONObject diff = diffs.getJSONObject(j);
                    String diffContent = diff.getString("diff");
                    counts = countAdditionsAndDeletions(diffContent);
                }
                return counts;
            });
            // 将 Future 对象添加到 futures 列表
            futures.add(future);
        }

        // 等待所有任务完成，并计算统计信息
        for (Future<int[]> future : futures) {
            try {
                int[] counts = future.get();
                totalAdditions += counts[0];
                totalDeletions += counts[1];
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

        return new int[]{totalAdditions, totalDeletions};
    }

    private static int[] getStatsForUser(ExecutorService executorService, String userName, JSONArray commitsArray, String since, String until) throws IOException {
        int totalAdditions = 0;
        int totalDeletions = 0;
        // 存储任务返回结果的列表
        List<Future<int[]>> futures = new ArrayList<>();
        for (int i = 0; i < commitsArray.length(); i++) {
            JSONObject commit = commitsArray.getJSONObject(i);
            // 提交任务到线程池
            Future<int[]> future = executorService.submit(() -> {
                if (since != null && until != null) {
                    String commitDate = commit.getString("created_at");
                    if (commitDate.compareTo(since) < 0 || commitDate.compareTo(until) > 0) {
                        return new int[]{0, 0};
                    }
                }
                if (!commit.getString("author_name").equals(userName)) {
                    return new int[]{0, 0};
                }
                String commitSha = commit.getString("id");
                HttpGet diffRequest = new HttpGet("http://gitlab.hzzcdz.com/api/v4/projects/" + projectID + "/repository/commits/" + commitSha + "/diff");
                diffRequest.addHeader("PRIVATE-TOKEN", privateToken);
                CloseableHttpClient client = HttpClients.createDefault();
                CloseableHttpResponse diffResponse = client.execute(diffRequest);

                if (diffResponse.getStatusLine().getStatusCode() != 200) {
                    System.out.println("Failed to get diff: " + diffResponse.getStatusLine().getReasonPhrase());
                    diffResponse.close();
                    return new int[]{0, 0};
                }

                String diffResponseBody = EntityUtils.toString(diffResponse.getEntity());
                diffResponse.close();

                JSONArray diffs = new JSONArray(diffResponseBody);
                int[] counts = new int[2];

                for (int j = 0; j < diffs.length(); j++) {
                    JSONObject diff = diffs.getJSONObject(j);
                    String diffContent = diff.getString("diff");
                    counts = countAdditionsAndDeletions(diffContent);
                }
                return counts;
            });
            // 将 Future 对象添加到 futures 列表
            futures.add(future);
        }

        // 等待所有任务完成，并计算统计信息
        for (Future<int[]> future : futures) {
            try {
                int[] counts = future.get();
                totalAdditions += counts[0];
                totalDeletions += counts[1];
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

        return new int[]{totalAdditions, totalDeletions};
    }
    /**
     * 代码行数换算
     * @param diffContent
     * @return
     */
    public static int[] countAdditionsAndDeletions(String diffContent) {
        String[] lines = diffContent.split("\n");
        int additions = 0;
        int deletions = 0;

        for (String line : lines) {
            if (line.startsWith("+") && !line.startsWith("+++")) {
                additions++;
            } else if (line.startsWith("-") && !line.startsWith("---")) {
                deletions++;
            }
        }

        return new int[]{additions, deletions};
    }

}

